using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace IUPUI.StellarResults
{
	/// <summary>
	/// Represents a simulation and the data used in the simulation.
	/// This is a simulation of a central computer that controls <see cref="Observatory"/>s 
	/// and dictates what <see cref="AstronomicalObject"/>s are being tracked.
	/// </summary>
	[Serializable]
	public class Simulation : Identifiable
	{
		#region Private Properties
		private DateTime m_CreatedDateTime;
		private DateTime m_LastUpdatedDateTime;
		private int m_Version;
		private DateTime m_StartDateTime;
		private ININ.Collections.NotifyingList<Observatory> m_Observatories =
			new ININ.Collections.NotifyingList<Observatory>();
		private ObservationType m_ObservationType = 
			ObservationType.RotatingEarth;
		private ININ.Collections.NotifyingList<AstronomicalObject> m_AstronomicalObjects = 
			new ININ.Collections.NotifyingList<AstronomicalObject>();

		private bool m_IsSimulationRunning = false;
		#endregion Private Properties

		#region Public Properties
		/// <summary>
		/// Gets or sets the date time when the simulation was created (UTC).
		/// </summary>
		/// <value>The created date time.</value>
		[Category("History")]
		[Description("Gets or sets the date time when the simulation was created (UTC).")]
		[ReadOnly(true)]
		public DateTime CreatedDateTime
		{
			get
			{
				return m_CreatedDateTime;
			}
			set
			{
				m_CreatedDateTime = value;
			}
		}

		/// <summary>
		/// Gets or sets the date time when the simulation was last updated (UTC).
		/// </summary>
		/// <value>The last updated date time.</value>
		[Category("History")]
		[Description("Gets or sets the date time when the simulation was last updated (UTC).")]
		[ReadOnly(true)]
		public DateTime LastUpdatedDateTime
		{
			get
			{
				return m_LastUpdatedDateTime;
			}
			set
			{
				m_LastUpdatedDateTime = value;
			}
		}

		/// <summary>
		/// Gets or sets the version.
		/// </summary>
		/// <value>The version.</value>
		[Category("History")]
		[Description("Gets or sets the version.")]
		[ReadOnly(true)]
		public int Version
		{
			get
			{
				return m_Version;
			}
			set
			{
				m_Version = value;
			}
		}

		/// <summary>
		/// Gets or sets the start date time (UTC).
		/// </summary>
		/// <remarks>Setting this to DateTime.MinValue indicates that the current datetime should be used.</remarks>
		/// <value>The start date time.</value>
		[Category("Simulation")]
		[Description("Gets or sets the start date time (UTC).")]
		public DateTime StartDateTime
		{
			get
			{
				if (m_StartDateTime == DateTime.MinValue)
				{
					m_StartDateTime = DateTime.UtcNow;
				}

				return m_StartDateTime;
			}
			set
			{
				m_StartDateTime = value;
			}
		}

		/// <summary>
		/// Gets or sets the type of the observation.
		/// </summary>
		/// <value>The type of the observation.</value>
		[Category("Simulation")]
		[Description("Gets or sets the type of the observation.")]
		public ObservationType ObservationType
		{
			get
			{
				return m_ObservationType;
			}
			set
			{
				m_ObservationType = value;
			}
		}

		/// <summary>
		/// Gets or sets the astronomical objects.
		/// </summary>
		/// <value>The astronomical objects.</value>
		[Category("Simulation")]
		[Description("Gets or sets the astronomical objects.")]
		public ININ.Collections.NotifyingList<AstronomicalObject> AstronomicalObjects
		{
			get
			{
				return m_AstronomicalObjects;
			}
			set
			{
				if (m_AstronomicalObjects != value)
				{
					m_AstronomicalObjects = value;
					OnAstronomicalObjectsChanged();
				}
			}
		}

		/// <summary>
		/// Gets or sets the observatories.
		/// </summary>
		/// <value>The observatories.</value>
		[Category("Simulation")]
		[Description("Gets or sets the observatories.")]
		public ININ.Collections.NotifyingList<Observatory> Observatories
		{
			get
			{
				return m_Observatories;
			}
			set
			{
				m_Observatories = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is simulation running.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is simulation running; otherwise, <c>false</c>.
		/// </value>
		[Bindable(false)]
		[Browsable(false)]
		[System.Xml.Serialization.XmlIgnore]
		public bool IsSimulationRunning
		{
			get
			{
				return m_IsSimulationRunning;
			}
			set
			{
				m_IsSimulationRunning = value;
			}
		}
		#endregion Public Properties

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="Simulation"/> class.
		/// </summary>
		public Simulation()
		{
			OnAstronomicalObjectsChanged();
			m_AstronomicalObjects.Modified += 
				new EventHandler(m_AstronomicalObjects_Modified);

			if (m_CreatedDateTime == DateTime.MinValue)
			{
				m_CreatedDateTime = DateTime.UtcNow;
			}

			if (m_LastUpdatedDateTime == DateTime.MinValue)
			{
				m_LastUpdatedDateTime = DateTime.UtcNow;
			}

			if (m_Version < 1)
			{
				m_Version = 1;
			}
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Simulation"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		public Simulation(
			string name)
			: this()
		{
			m_Name = name;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Simulation"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="observationType">Type of the observation.</param>
		public Simulation(
			string name,
			ObservationType observationType)
			: this(name)
		{
			m_ObservationType = observationType;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Simulation"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="observationType">Type of the observation.</param>
		/// <param name="startDateTime">The start date time.</param>
		public Simulation(
			string name,
			ObservationType observationType,
			DateTime startDateTime)
			: this(name, observationType)
		{
			m_StartDateTime = startDateTime;
		}
		#endregion Constructors

		/// <summary>
		/// Handles the Modified event of the m_AstronomicalObjects control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void m_AstronomicalObjects_Modified(object sender, EventArgs e)
		{
			OnAstronomicalObjectsChanged();
		}

		/// <summary>
		/// Called when [astronomical objects changed].
		/// </summary>
		private void OnAstronomicalObjectsChanged()
		{
		}
	}
}
